package com.bestdreamer.synch.account3;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Condition 控制线程通信
 */
public class Account {

    // 显示定义 Lock 对象
    private final Lock lock = new ReentrantLock();
    // 获得指定 Lock 对象对应的 Condition
    private final Condition cond = lock.newCondition();

    // 封装账户编号、账户余额两个 Field
    private String accountNo;
    private double balance;

    // 标识账户中是否已有存款的旗标
    private boolean flag = false;

    public Account(){}

    public Account(String accountNo, double balance){
        this.accountNo = accountNo;
        this.balance = balance;
    }
    public String getAccountNo() {
        return accountNo;
    }
    public void setAccountNo(String accountNo) {
        this.accountNo = accountNo;
    }

    // 因为账户余额不允许随意修改，所以只为 balance 提供 getter 方法
    public double getBalance(){
        return this.balance;
    }

    /**
     * 提供一个线程安全的 draw() 方法来完成取钱操作
     */
    public void draw(double drawAmount){
        // 加锁
        lock.lock();
        try{
            // 如果 flag 为假，表名账户中还没有人存钱进去，取钱方法阻塞
            if(!flag){
                cond.await();
            }else {
                // 执行取钱操作
                System.out.println(Thread.currentThread().getName()+"取钱:"+drawAmount);
                balance -= drawAmount;
                System.out.println("账户余额为："+balance);
                // 将标识账户是否已有存款的旗标设为 false
                flag = false;
                // 唤醒其他线程
                notifyAll();
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public synchronized void deposit(double depositAccount){
        lock.lock();
        try{
            // 如果 flag 为真，表明账户中已有人存钱进去，存钱方法阻塞
            if(flag){
                cond.await();
            }else {
                // 执行存款操作
                System.out.println(Thread.currentThread().getName()+"存款："+depositAccount);
                balance += depositAccount;
                System.out.println("账户余额为："+balance);
                // 将表示账户是否已有存款的旗标设为 true
                flag = true;
                // 唤醒其他线程
                notifyAll();
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public int hashCode(){
        return accountNo.hashCode();
    }

    public boolean equals(Object obj){
        if(this == obj){
            return true;
        }
        if( obj != null && obj.getClass() == Account.class){
            Account target = (Account)obj;
            return target.getAccountNo().equals(accountNo);
        }
        return false;
    }

}
